using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Serialization;

public class Dot : MonoBehaviour
{
    private Vector2 firstPosition;

    private Vector2 finalPosition;

    private float swipeAngle;

    private int swipeResist = 1;

    public Broad broad;

    public GameObject other;
    [FormerlySerializedAs("PreColumn")] public int preColumn;
    [FormerlySerializedAs("PreRow")] public int preRow;


    public int column;
    public int row;

    public int targetX;
    public int targetY;

    public bool isMatch;

    // Start is called before the first frame update
    void Start()
    {
        broad = FindObjectOfType<Broad>();
        targetX = (int)transform.position.x;
        targetY = (int)transform.position.y;
        column = targetX;
        row = targetY;
        preColumn = column;
        preRow = row;
    }

    // Update is called once per frame
    void Update()
    {
        FindMath();
        if (isMatch)
        {
            var spriteRenderer = GetComponent<SpriteRenderer>();
            spriteRenderer.color = new Color(1f, 1f, 1f, .2f);
        }

        targetX = column;
        targetY = row;
        if (Mathf.Abs(targetX - transform.position.x) > .1)
        {
            // Move towards the target
            var position = transform.position;
            var tempPosition = new Vector2(targetX, position.y);
            position = Vector2.Lerp(position, tempPosition, .6f);
            transform.position = position;
            if (broad.AllDots != null && broad.AllDots[column, row] != gameObject)
            {
                broad.AllDots[column, row] = gameObject;
            }
        }
        else if (Mathf.Abs(targetY - transform.position.y) > .1)
        {
            // Move towards the target
            var position = transform.position;
            var tempPosition = new Vector2(position.x, targetY);
            position = Vector2.Lerp(position, tempPosition, .6f);
            transform.position = position;
            if (gameObject != null && broad.AllDots[column, row] != gameObject)
            {
                broad.AllDots[column, row] = gameObject;
            }
        }
        else
        {
            var tempPosition = new Vector2(targetX, targetY);
            transform.position = tempPosition;
        }
    }

    public void OnMouseDown()
    {
        // Debug.Log("Mouse Down");
        firstPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    }

    public void OnMouseUp()
    {
        // Debug.Log("Mouse Up");
        finalPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        CalculateAngle();
    }

    private void CalculateAngle()
    {
        if (Mathf.Abs(finalPosition.y - firstPosition.y) > swipeResist ||
            Mathf.Abs(finalPosition.x - firstPosition.x) > swipeResist)
        {
            swipeAngle = Mathf.Atan2(finalPosition.y - firstPosition.y, finalPosition.x - firstPosition.x) * 180 /
                         Mathf.PI;
            Debug.Log(swipeAngle);
            MovePiece();
        }
    }

    private void MovePiece()
    {
        switch (swipeAngle)
        {
            case > -45 and <= 45 when column < broad.width - 1:
                //Right Swipe
                SwapPieces(Vector2.right);
                break;
            case > 45 and <= 135 when row < broad.height - 1:
                //Up Swipe
                SwapPieces(Vector2.up);
                break;
            case > 135 or <= -135 when column > 0:
                //Left Swipe
                SwapPieces(Vector2.left);
                break;
            case < -45 and >= -135 when row > 0:
                //Down Swipe
                SwapPieces(Vector2.down);
                break;
        }

        StartCoroutine(CheckBack());
    }

    private IEnumerator CheckBack()
    {
        yield return new WaitForSeconds(.5f);
        if (other != null)
        {
            var otherDot = other.GetComponent<Dot>();
            if (!isMatch && !otherDot.isMatch)
            {
                otherDot.row = row;
                otherDot.column = column;
                row = preRow;
                column = preColumn;
            }
            else
            {
                preColumn = column;
                preRow = row;
                otherDot.preRow = row;
                otherDot.preColumn = column;
                broad.DestroyMatches();
            }

            other = null;
        }
    }




    private void SwapPieces(Vector2 right)
    {
        var temp = broad.AllDots[column + (int)right.x, row + (int)right.y];
        broad.AllDots[column + (int)right.x, row + (int)right.y] = gameObject;
        broad.AllDots[column, row] = temp;
        var component = temp.GetComponent<Dot>();
        if (component != null)
        {
            component.column = column;
            component.row = row;
        }
        other = temp;
        column += (int)right.x;
        row += (int)right.y;
    }

    private void FindMath()
    {
        if (column > 0 && column < broad.width - 1)
        {
            var leftDot = broad.AllDots[column - 1, row];
            var rightDot = broad.AllDots[column + 1, row];
            if (leftDot != null && rightDot != null)
            {
                if (leftDot.CompareTag(gameObject.tag) && rightDot.CompareTag(gameObject.tag))
                {
                    leftDot.GetComponent<Dot>().isMatch = true;
                    rightDot.GetComponent<Dot>().isMatch = true;
                    isMatch = true;
                }
            }
        }

        if (row > 0 && row < broad.height - 1)
        {
            var upDot = broad.AllDots[column, row + 1];
            var downDot = broad.AllDots[column, row - 1];
            if (upDot != null && downDot != null)
            {
                if (upDot.CompareTag(gameObject.tag) && downDot.CompareTag(gameObject.tag))
                {
                    upDot.GetComponent<Dot>().isMatch = true;
                    downDot.GetComponent<Dot>().isMatch = true;
                    isMatch = true;
                }
            }
        }
    }
}